

package com.base.test.dao.aspect;

import org.apache.shardingsphere.api.hint.HintManager;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

/**
 * 主库数据源，切面处理类
 *
 * @author carl
 * @since 1.0.0
 */
@Aspect
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MasterDsAspect {
    protected Logger logger = LoggerFactory.getLogger(getClass());
    protected static final String HINT_NUM = "hint_num";

    @Pointcut("@annotation(com.base.test.dao.annotation.MasterDataSource) " +
            "|| @within(com.base.test.dao.annotation.MasterDataSource)")
    public void masterDsPointCut() {

    }

    @Around("masterDsPointCut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        try {
            if (!HintManager.isMasterRouteOnly()) {
                HintManager hintManager = HintManager.getInstance();
                hintManager.setMasterRouteOnly();
            }
            this.incrementHintNum();
            return point.proceed();
        } finally {
            Integer hintNum = decrementHintNum();
            if(hintNum==0) {
                HintManager.clear();
            }
        }
    }

    public Integer incrementHintNum(){
        Integer hintNum = MDC.get(HINT_NUM)==null ? 0: Integer.valueOf(MDC.get(HINT_NUM));
        hintNum++;
        MDC.put(HINT_NUM,String.valueOf(hintNum));
        return hintNum;
    }

    public Integer decrementHintNum(){
        Integer hintNum = MDC.get(HINT_NUM)==null ? 0: Integer.valueOf(MDC.get(HINT_NUM));
        hintNum--;
        MDC.put(HINT_NUM,String.valueOf(hintNum));
        return hintNum;
    }
}